package com.goudan.ojcloudjudgeservice.rabbitmq;

import com.goudan.ojcloudjudgeservice.service.JudgeService;
import com.goudan.ojcommon.config.RabbitMqConfig;
import com.goudan.ojmodel.entity.QuestionSubmit;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class Consumer {

    @Resource
    private JudgeService JudgeServiceImpl;

    //最大重试次数
    private static final int MAX_RETRY = 3;

    @SneakyThrows
    @RabbitListener(queues = RabbitMqConfig.QUEUE_NAME, ackMode = "MANUAL")
    public void receiveMessage(String message, Channel channel,
                               @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                               @Header(name = "x-death", required = false) java.util.List<?> xDeath) {
        log.info("receiveMessage message = {}", message);
        try {
            long questionSubmitId = Long.parseLong(message);
            QuestionSubmit result = JudgeServiceImpl.doJudge(questionSubmitId);
            log.info("Judge result: {}", result);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            log.error("处理消息失败: {}", message, e);
            int retryCount = getRetryCount(xDeath);
            if (retryCount >= MAX_RETRY) {
                log.warn("消息重试超过最大次数，丢入死信队列: {}", message);
                channel.basicNack(deliveryTag, false, false); // 进入死信队列
            } else {
                log.warn("重试第 {} 次", retryCount + 1);
                channel.basicNack(deliveryTag, false, true); // 重新入队
            }
        }
    }

    private int getRetryCount(List<?> xDeath) {
        if (xDeath == null || xDeath.isEmpty()) return 0;
        try {
            Object xDeathEntry = xDeath.get(0);
            if (xDeathEntry instanceof Map) {
                Object count = ((Map<?, ?>) xDeathEntry).get("count");
                if (count instanceof Long) {
                    return ((Long) count).intValue();
                }
            }
        } catch (Exception ignored) {}
        return 0;
    }
}
